<?php
/**
 * This file is part of the UXLabs project.
 *
 * (c) UXLabs project <http://code.uxlabs.me>
 *
 */

namespace uxl\app\api\controllers;

use uxl\app\api\Bootstrap;
use uxl\app\api\components\IApiMethod;
use uxl\app\api\components\ResultStatus;
use uxl\app\api\models\AccessToken;
use Yii;

/**
 * 接口方法基础处理
 * @package uxl\app\api\controllers
 * @author ice deng <ice.deng@qq.com>
 */
class MethodBaseController extends BaseController
{
    /**
     * @var string 接口方法配置文件在配置params中的key
     */
    protected $methodConfigParamsKey = 'appApiMethodConfig';
    /**
     * @var null|string 接口方法配置文件
     */
    protected $methodConfig = null;
    /**
     * @var array|null 访问授权token信息
     */
    protected $accessToken;

    /**
     * 获取请求类型
     * @return string
     */
    protected function getRequestType()
    {
        return static::REQUEST_TYPE_METHOD;
    }

    /**
     * 校验accessKey并设置变量$secretKey的值
     * @return bool
     */
    protected function checkAccessKey()
    {
        /** @var AccessToken $model */
        $model = Yii::$container->get(AccessToken::className());
        $this->accessToken = $model->getByAccessKey($this->parameters->accessKey);
        if ($this->accessToken == false) {
            $errorMsg = 'access key不存在.';
            $this->setErrorResponse(ResultStatus::ACCESS_KEY_ERROR, $errorMsg);
            $this->errorLog($errorMsg);
            return false;
        }
        if ($this->accessToken['status'] != 1) {
            $errorMsg = 'access key无效.';
            $this->setErrorResponse(ResultStatus::ACCESS_KEY_ERROR, $errorMsg);
            $this->errorLog($errorMsg);
            return false;
        }
        // 过期判断
        if ($this->accessToken['expiresIn'] != 0 && $this->accessToken['expiresIn'] < $this->accessToken['t']) {
            $errorMsg = 'access key过期.';
            $this->setErrorResponse(ResultStatus::ACCESS_KEY_EXPIRES, $errorMsg);
            $this->errorLog($errorMsg);
            return false;
        }
        $this->secretKey = $this->accessToken['secretKey'];
        return true;
    }

    /**
     * 获取方法配置文件路径
     * @return bool|null|string
     */
    protected function getMethodConfigPath()
    {
        if ($this->methodConfig != null) {
            return $this->methodConfig;
        }
        if (isset(Yii::$app->params[$this->methodConfigParamsKey])) {
            return Yii::$app->params[$this->methodConfigParamsKey];
        }
        if (Bootstrap::$methodConfig != null) {
            return Bootstrap::$methodConfig;
        }
        return Yii::getAlias('@app/config/api_method.php');
    }

    /**
     * 参数模式处理
     * @return \uxl\app\api\components\ResultResponse
     */
    protected function parameterModelHandle()
    {
        $version = $this->parameters->version;
        $version = empty($version) ? '1.0.0' : $version;
        $configFile = $this->getMethodConfigPath();
        // 判断是否存在多版本配置
        $configFileVersion = substr($configFile, 0, strlen($configFile) - 3) . '-' . $version . '.php';
        // 优先加载相应版本的配置文件
        if (file_exists($configFileVersion)) {
            $configFile = $configFileVersion;
        }
        $config = require($configFile);
        // 未加载成功配置文件
        if ($config == null) {
            $errorMsg = '方法配置文件路径错误.';
            $this->errorLog($errorMsg . $configFile);
            return $this->setErrorResponse(ResultStatus::ERROR, $errorMsg);
        }
        // 配置文件不是数组
        if (is_array($config) == false) {
            $errorMsg = '方法配置文件内容必须是PHP数组.';
            $this->errorLog($errorMsg . $configFile);
            return $this->setErrorResponse(ResultStatus::ERROR, $errorMsg);
        }
        $method = $this->parameters->method;
        // 没有此请求方法的配置
        if (isset($config[$method]) == false) {
            $errorMsg = '没有此请求方法的配置.';
            $this->errorLog($errorMsg . $configFile);
            return $this->setErrorResponse(ResultStatus::ERROR, $errorMsg);
        }
        $clsConfig = $config[$method];
        /** @var IApiMethod $clsInstance */
        $clsInstance = Yii::createObject($clsConfig);
        $clsInstance->setParamData($this->parameters->getDataValue());
        $clsInstance->setAccessToken($this->accessToken);
        $clsInstance->runAction();
        $respStatus = $clsInstance->getStatus();
        if ($respStatus == ResultStatus::SUCCESS) {
            $result = $clsInstance->getResult();
            return $this->setResultResponse($result);
        } else {
            $errorMsg = $clsInstance->getErrorMsg();
            $this->errorLog($errorMsg);
            return $this->setErrorResponse($respStatus, $errorMsg);
        }
    }

    /**
     * 参数模式处理业务
     * @return \uxl\app\api\components\ResultResponse
     */
    public function actionIndex()
    {
        return $this->parameterModelHandle();
    }

}